

export const isUndefined = (o: any): o is undefined => {
  return o === undefined
}

export const isNull = (o: any): o is null => {
  return o === null
}

export const isFunction = (f: any): f is Function => {
  return f && {}.toString.call(f) === '[object Function]'
}

export const isArray = (a: any): a is [] => {
  if (typeof Array.isArray === "function") {
    return Array.isArray(a)
  } else {
    return Object.prototype.toString.call(a) === "[object Array]"
  }
}

export const isObject = (o: any): o is object => {
  return o === Object(o);
}

export const isBoolean = (b: any): b is boolean => {
  return b === !!b
}

export const isNumber = (n: any): n is number => {
  return n === +n
}

type Integer = number

export const isInteger = (i: any): i is Integer => {
  return Number.isInteger(i) && Math.abs(i) <= Number.MAX_SAFE_INTEGER
}

export const isString = (s: any): s is string => {
  return s === s + ''
}

export const isEmpty = (o: any): boolean => {
  if (isString(o) || isArray(o)) {
    return o.length === 0
  } else if (isNumber(o) || isBoolean(o) || isInteger(o)) {
    return (o + '').length === 0
  } else if (isObject(o)) {
    Object.keys(o).length === 0
  }
  return false
}

export const canUse = (o: any) : boolean => {
  return !isUndefined(o) && !isNull(o)
}